﻿//------------------------------------------------------------------------------ 
// <copyright file="Utility.cs" company="Fm Computer">
//     Copyright (c) Fm Computer di Menatti Fulvia.  All rights reserved.
// </copyright>
//-----------------------------------------------------------------------------
namespace FmjQuery
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Reflection;
    using System.Runtime.Serialization.Json;
    using System.Text;
    using System.Web.UI;

    /// <summary>
    /// Utility for manage jquery Controls
    /// </summary>
    public static class Utility
    {
        #region Manage Image
        /// <summary>
        /// Gets url of webresource image
        /// </summary>
        /// <param name="page">page where is image</param>
        /// <param name="typeControl">type control</param>
        /// <param name="imgUrl">url of image</param>
        /// <returns>webresource url</returns>
        public static string GetImageResourceUrl(this Page page, Type typeControl, string imgUrl)
        {
            return page.ClientScript.GetWebResourceUrl(typeControl, imgUrl);
        }
        #endregion

        #region Json
        /// <summary>
        /// Searilize class to Json string
        /// </summary>
        /// <typeparam name="T">type of class</typeparam>
        /// <param name="obj">original class</param>
        /// <returns>serialization class</returns>
        public static string SerializeJSon<T>(T obj)
        {
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());

            using (MemoryStream ms = new MemoryStream())
            {
                serializer.WriteObject(ms, obj);
                return Encoding.Default.GetString(ms.ToArray());
            }
        }

        /// <summary>
        /// Deserialize json string
        /// </summary>
        /// <typeparam name="T">type of destination class</typeparam>
        /// <param name="json">original json string</param>
        /// <returns>Destion Class</returns>
        public static T DeserializeJSon<T>(string json)
        {
            T obj = Activator.CreateInstance<T>();

            using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
                obj = (T) serializer.ReadObject(ms);
            }

            return obj;
        }
        #endregion

        #region Register Script
        /// <summary>
        /// Insert startup script into page
        /// </summary>
        /// <param name="page">Page where insert script</param>
        /// <param name="keyName">key of name script</param>
        /// <param name="scriptText">script code</param>
        public static void RegisterStartUpScript(Page page, string keyName, string scriptText)
        {
            ClientScriptManager manager = page.ClientScript;

            if (!manager.IsStartupScriptRegistered(keyName))
            {
                manager.RegisterStartupScript(page.GetType(), keyName, string.Format(Properties.Settings.Default.Js_IncludeScript, keyName, scriptText), false);
            }
        }
        #endregion

        #region Manage Resource
        /// <summary>
        /// Register web resource into page
        /// </summary>
        /// <param name="page">page wher insert resource</param>
        /// <param name="typeControl">type of control that need include resource</param>
        /// <param name="source"><see cref="JSource"/> that include into page</param>
        /// <param name="images">Collection of <see cref="CssImage">CssImage</see> for create resource</param>
        internal static void RegisterjSource(Page page, Type typeControl, JSource source, IEnumerable<CssImage> images)
        {
            switch (source.Type)
            {
                case JSourceType.webService:
                {
                    RegisterWebService(page, typeControl, source);
                    break;
                }

                case JSourceType.css_dynamic:
                {
                    RegisterDynamicCss(page, typeControl, source, images);
                    break;
                }

                default:
                {
                    if (source.IsWebResource)
                    {
                        RegisterResource(page, typeControl, source);
                    }
                    else
                    {
                        RegisterExternalResource(page, typeControl, source);
                    }

                    break;
                }
            }
        }

        /// <summary>
        /// Register external resource into page
        /// </summary>
        /// <param name="page">page wher insert resource</param>
        /// <param name="typeControl">type of control that need include resource</param>
        /// <param name="source"><see cref="JSource"/> that include into page</param>
        internal static void RegisterExternalResource(Page page, Type typeControl, JSource source)
        {
            string include = (source.Type == JSourceType.javascript) ? Properties.Settings.Default.WebResource_Js : Properties.Settings.Default.WebResource_Css;
            page.RegisterHeaderControl(string.Format(include, source.Name, source.Url), source.Name);
        }

        /// <summary>
        /// Register Resource into page
        /// </summary>
        /// <param name="page">page where insert resource</param>
        /// <param name="typeControl">Type control</param>
        /// <param name="source"><see cref="JSource"/> that include into page</param>
        internal static void RegisterResource(Page page, Type typeControl, JSource source)
        {
            string include = (source.Type == JSourceType.javascript) ? Properties.Settings.Default.WebResource_Js : Properties.Settings.Default.WebResource_Css;
            if (source.Type == JSourceType.javascript)
            {
                page.RegisterHeaderControl(string.Format(include, source.Name, page.ClientScript.GetWebResourceUrl(typeControl, source.Url)), source.Name);
            }
            else
            {
                page.RegisterHeaderControl(string.Format(include, source.Name, page.ClientScript.GetWebResourceUrl(typeControl, source.Url)), source.Name);
            }
        }

        /// <summary>
        /// Register Dynamic css into page
        /// </summary>
        /// <param name="page">page where insert resource</param>
        /// <param name="typeControl">type control</param>
        /// <param name="source"><see cref="JSource"/> that include into page</param>
        /// <param name="images">list of image that ad into css</param>
        internal static void RegisterDynamicCss(Page page, Type typeControl, JSource source, IEnumerable<CssImage> images)
        {
            Assembly asm = Assembly.GetExecutingAssembly();
            Stream str = asm.GetManifestResourceStream(source.Url);

            if (str != null)
            {
                StringBuilder builder = new StringBuilder();

                using (StreamReader sr = new StreamReader(str))
                {
                    string line;

                    while ((line = sr.ReadLine()) != null)
                    {
                        builder.Append(line);
                    }
                }

                string css = builder.ToString();

                if (images != null)
                {
                    foreach (CssImage image in images)
                    {
                        css = css.Replace(image.ID, GetImageResourceUrl(page, typeControl, image.Url));
                    }
                }

                page.RegisterHeaderControl(string.Format(Properties.Settings.Default.WebResource_DynamicCss, css), source.Name);
            }
        }

        /// <summary>
        /// Register LiteralControl into Header page
        /// </summary>
        /// <param name="page">page where insert control</param>
        /// <param name="text">Text for control</param>
        /// <param name="idLiteral">code of literal control</param>
        internal static void RegisterHeaderControl(this Page page, string text, string idLiteral)
        {
            LiteralControl literal = new LiteralControl(text) { ID = idLiteral };
            
            bool justExist = false;
            foreach (Control c in page.Header.Controls)
            {
                if (c.ID != null)
                {
                    if (c.ID.Equals(idLiteral))
                    {
                        justExist = true;
                        break;
                    }
                }
            }

            if (!justExist)
            {
                page.Header.Controls.Add(literal);
            }
        }
        #endregion

        #region WebService
        /// <summary>
        /// Register new jQuery plu-in for webService
        /// </summary>
        /// <param name="page">page where insert resource</param>
        /// <param name="typeControl">Type control</param>
        /// <param name="source"><see cref="JSource"/> web service that register</param>
        internal static void RegisterWebService(Page page, Type typeControl, JSource source)
        {
            StringBuilder builder = new StringBuilder("(function($){$.extend({");

            builder.AppendFormat("Wb_{0}:function(methodName, dataService, successFunction, errorFunction)", source.Name);
            builder.Append("{if(dataService==null){dataService=new Object();}");
            builder.AppendFormat("$.ajaxDotNet('{0}/' + methodName,", source.Url);
            builder.Append("{verb: 'POST', data: dataService, success: successFunction, error: errorFunction});}});})(jQuery);");

            page.Header.Controls.Add(new LiteralControl(string.Format(Properties.Settings.Default.Js_IncludeScript, source.Name, builder)));
        }

        #endregion

        #region Manage String
        /// <summary>
        /// Parse string for use by client
        /// </summary>
        /// <param name="phrase">phrase that parse</param>
        /// <returns>parsing string</returns>
        internal static string ParseStringToClient(this string phrase)
        {
            StringBuilder builder = new StringBuilder();

            for (int x = 0; x < phrase.Length; x++)
            {
                if (phrase[x].Equals('\''))
                {
                    if (!x.Equals(0))
                    {
                        if (!phrase[x - 1].Equals(@"\"))
                        {
                            builder.Append(@"\");
                        }
                    }
                }

                builder.Append(phrase[x]);
            }

            return builder.ToString();
        }
        #endregion

        #region Manage Client NameSpace
        /// <summary>
        /// Get list of value into enum
        /// </summary>
        /// <param name="type">type of enum</param>
        /// <returns>list with name and value into enum</returns>
        internal static IEnumerable<KeyValuePair<string, int>> GetListValueEnum(Type type)
        {
            List<KeyValuePair<string, int>> values = new List<KeyValuePair<string, int>>();

            foreach (string name in Enum.GetNames(type))
            {
                values.Add(new KeyValuePair<string, int>(name, (int)Enum.Parse(type, name)));
            }

            return values;
        }

        /// <summary>
        /// Register enums into web page
        /// </summary>
        /// <param name="page">page where insert nameSpace</param>
        /// <param name="nameSpace">client nameSpase descriptor</param>
        internal static void RegisterNameSpaces(Page page, ClientNameSpace nameSpace)
        {
            if (nameSpace.Enums.Count > 0)
            {
                // check namespace
                string nameCheck = string.Concat("CheckNameSpace_", string.Concat("ck_", nameSpace.NameSpace));
                string script = string.Concat("if(!$.", nameSpace.NameSpace, "){ $.", nameSpace.NameSpace, " = new Object();}");

                page.RegisterHeaderControl(string.Format(Properties.Settings.Default.Js_IncludeScript, nameCheck, script), nameSpace.NameSpace);

                // create client enum
                StringBuilder builder = new StringBuilder();

                foreach (ClientEnum clientEnum in nameSpace.Enums)
                {
                    bool first = true;

                    builder.Append(string.Concat("$.", nameSpace.NameSpace, ".", clientEnum.EnumName));
                    builder.Append(" = {");

                    foreach (KeyValuePair<string, int> en in GetListValueEnum(clientEnum.EnumType))
                    {
                        if (!first)
                        {
                            builder.Append(",");
                        }
                        else
                        {
                            first = false;
                        }

                        builder.AppendFormat("{0}: {1}", en.Key, en.Value);
                    }

                    builder.Append("};");
                }

                page.RegisterHeaderControl(string.Format(Properties.Settings.Default.Js_IncludeScript, string.Concat("Declare_", nameSpace.NameSpace), builder), string.Concat("dl_", nameSpace.NameSpace));
            }
        }
        #endregion

        #region Manage Themes
        /// <summary>
        /// Register component for use Theme
        /// </summary>
        /// <param name="page">page where insert files</param>
        /// <param name="typeControl">type control</param>
        /// <param name="theme">type of theme</param>
        internal static void RegisterThemeComponent(Page page, Type typeControl, Themes theme)
        {
            // jquerymanager = ui.core ui.theme
            if (typeControl.Equals(typeof(JQueryManager)))
            {
                string thname = Properties.Settings.Default.Css_Theme_Manage_Name;

                string nameTheme = theme.ToString();
                string thm = string.Format(Properties.Settings.Default.Css_Theme_Manage_Url, nameTheme);
                string gloss = string.Format(Properties.Settings.Default.Image_Theme_gloss, nameTheme);
                string hig100 = string.Format(Properties.Settings.Default.Image_Theme_hight100, nameTheme);
                string glass6 = string.Format(Properties.Settings.Default.Image_Theme_glass6, nameTheme);
                string glass5 = string.Format(Properties.Settings.Default.Image_Theme_glass5, nameTheme);
                string glass65 = string.Format(Properties.Settings.Default.Image_Theme_glass65, nameTheme);
                string glass9 = string.Format(Properties.Settings.Default.Image_Theme_glass9, nameTheme);
                string hig75 = string.Format(Properties.Settings.Default.Image_Theme_hight75, nameTheme);
                string dia18 = string.Format(Properties.Settings.Default.Image_Theme_Diagonal18, nameTheme);
                string ico222 = string.Format(Properties.Settings.Default.Image_Theme_icon222, nameTheme);
                string icofff = string.Format(Properties.Settings.Default.Image_Theme_icofff, nameTheme);
                string icoef8 = string.Format(Properties.Settings.Default.Image_Theme_icoef8, nameTheme);
                string ico228 = string.Format(Properties.Settings.Default.Image_Theme_ico228, nameTheme);
                string icoffd = string.Format(Properties.Settings.Default.Image_Theme_icoffd, nameTheme);
                string dia20 = string.Format(Properties.Settings.Default.Image_Theme_Diagonal20, nameTheme);
                string icofcd = string.Format(Properties.Settings.Default.Image_Theme_icofcd, nameTheme);
                string flat = string.Format(Properties.Settings.Default.Image_Theme_flat, nameTheme);
                string flat2 = string.Format(Properties.Settings.Default.Image_Theme_flat2, nameTheme);

                RegisterResource(page, typeControl, new JSource(Properties.Settings.Default.Css_Theme_Core_Name, Properties.Settings.Default.Css_Theme_Core_Url, JSourceType.css, true));

                List<CssImage> images = new List<CssImage> { new CssImage(thname, "GLOSS", gloss, true), new CssImage(thname, "HIG100", hig100, true), new CssImage(thname, "GLASS65", glass65), new CssImage(thname, "GLASS6", glass6, true), new CssImage(thname, "GLASS5", glass5), new CssImage(thname, "HIG75", hig75, true), new CssImage(thname, "DIA18", dia18), new CssImage(thname, "ICO222", ico222), new CssImage(thname, "ICOFFF", icofff), new CssImage(thname, "ICOEF8", icoef8), new CssImage(thname, "ICO228", ico228), new CssImage(thname, "ICOFFD", icoffd), new CssImage(thname, "DIA20", dia20), new CssImage(thname, "FLAT2", flat2), new CssImage(thname, "FLAT", flat), new CssImage(thname, "ICOFCD", icofcd), new CssImage(thname, "GLASS9", glass9) };
                RegisterjSource(page, typeControl, new JSource(thname, thm, JSourceType.css_dynamic, true), images);
            }

            IManageBaseScript manager = JQueryManager.GetCurrent(page);

            // Tabs
            if (typeControl.Equals(typeof(JTabs)) || manager.Tab)
            {
                RegisterResource(page, typeControl, new JSource(Properties.Settings.Default.Css_Theme_Tabs_Name, Properties.Settings.Default.Css_Theme_Tabs_Url, JSourceType.css, true));
            }

            // Accordion
            if (typeControl.Equals(typeof(JAccordion)) || manager.Accordion)
            {
                RegisterResource(page, typeControl, new JSource(Properties.Settings.Default.Css_Theme_Accordion_Name, Properties.Settings.Default.Css_Theme_Accordion_Url, JSourceType.css, true));
            }

            // DatePicker
            if (typeControl.Equals(typeof(JDatePicker)) || manager.DatePicker)
            {
                RegisterResource(page, typeControl, new JSource(Properties.Settings.Default.Css_Theme_Date_Name, Properties.Settings.Default.Css_Theme_Date_Url, JSourceType.css, true));
            }

            // Resizable
            if (typeControl.Equals(typeof(JResizable)) || manager.Resizable)
            {
                RegisterResource(page, typeControl, new JSource(Properties.Settings.Default.Css_Theme_Resizable_Name, Properties.Settings.Default.Css_Theme_Resizable_Url, JSourceType.css, true));
            }

            // Dialog
            if (typeControl.Equals(typeof(JDialog)) || manager.Dialog)
            {
                RegisterResource(page, typeControl, new JSource(Properties.Settings.Default.Css_Theme_Dialog_Name, Properties.Settings.Default.Css_Theme_Dialog_Url, JSourceType.css, true));
                RegisterResource(page, typeControl, new JSource(Properties.Settings.Default.Css_Theme_Resizable_Name, Properties.Settings.Default.Css_Theme_Resizable_Url, JSourceType.css, true));
            }

            // Slider
        }
        #endregion

        #region Manage Culture
        /// <summary>
        /// Insert languages file into web page
        /// </summary>
        /// <param name="page">page where insert into page</param>
        /// <param name="typeControl">type control</param>
        /// <param name="defaultLanguage">default language</param>
        /// <param name="includeDefault">indicates whether include default language and page language</param>
        internal static void RegisterLanguages(Page page, Type typeControl, string defaultLanguage, bool includeDefault)
        {
            if (includeDefault && string.IsNullOrEmpty(defaultLanguage))
            {
                defaultLanguage = "en";
            }

            // include defualt language)
            if (includeDefault)
            {
                RegisterLanguage(page, typeControl, defaultLanguage);
            }

            // check language
            if (page.Request.UserLanguages.Length > 0)
            {
                string currentLanguage = page.Request.UserLanguages[0];

                if (!includeDefault || !defaultLanguage.Equals(currentLanguage))
                {
                    RegisterLanguage(page, typeControl, currentLanguage);
                }
            }
        }

        /// <summary>
        /// Insert language file into web page
        /// </summary>
        /// <param name="page">page where insert into page</param>
        /// <param name="typeControl">type control</param>
        /// <param name="language">language that insert</param>
        private static void RegisterLanguage(Page page, Type typeControl, string language)
        {
            string nameType = typeControl.Name;
            string key = string.Concat("Language_", nameType, "_", language);

            RegisterjSource(page, typeControl, new JSource(key, string.Format(Properties.Settings.Default.Js_Languages, nameType, language), JSourceType.javascript, true), null);
        }
        #endregion
    }
}
